package com.zhdl.network.service.impl;

import com.project.command.faq.event.behavior.BehaviorPerform;
import com.project.command.instruction.bo.SingleInstruction;
import com.project.common.util.ByteHelper;
import com.zhdl.common.util.IdUtil;
import com.zhdl.modules.tools.IntToHexUtil;
import com.zhdl.modules.tools.PublicTools;
import com.zhdl.network.demotcp.analysis.MemoBusAnalysisImpl;
import com.zhdl.network.modbus.after.ModbusAfterService;
import com.zhdl.network.modbus.analysis.ModbusAnalysis;
import com.zhdl.network.modbus.request.WriteSingleKeepRegisterReq;
import com.zhdl.network.modbustcp.ModbusTcpRespPkg;
import com.zhdl.network.pcb.after.PcbAfterService;
import com.zhdl.network.service.PcbService;
import com.zhdl.network.service.conf.PortConf;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;

import static com.project.command.instruction.strategy.abs.AbsDic.INSTRUCTION_DEFAULT_HEX;

@Slf4j
@Service
public class PcbServiceImpl implements PcbService {


    @Resource
    private BehaviorPerform behaviorPerform;

    @Resource
    private PortConf portConf;

//    @PostConstruct
//    public void inittest(){
//        System.out.println("============="+portConf.getComPortWest());
//        System.out.println("============="+portConf.getComPortEast());
//        System.out.println("============="+portConf.getComPortSlag());
//        System.out.println("============="+portConf.getTcpPortRobot());
//        System.out.println("============="+portConf.getTcpPortIo());
//    }

    /**
     * 发送指令 - 参考模板
     */
    @Override
    public void sendCmd() {
        SingleInstruction instruction = new SingleInstruction();
        instruction.setInstructionId(IdUtil.getUUID_8());
        instruction.setInstruction("cmd");
        instruction.setBeforeInstructionName(INSTRUCTION_DEFAULT_HEX);
        //默认使用com.zhdl.instruction.strategy包下后置策略
        instruction.setAfterInstructionName(ModbusAfterService.MODBUS_AFTER_SERVICE);
        //客户端通信地址, 串口为数字, 网口为ip+端口       数据来源 : port_comm 或 port_socket 表
        instruction.setPortKey("7");
        //设置协议  数据来源 : protocols 表
        instruction.setProtocols(ModbusAnalysis.MODBUS_ANALYSIS);
        behaviorPerform.perform(instruction);
    }

    /**
     * 发送指令 - 灵活
     *
     * @param cmd 指令
     */
//    @Override
//    public void sendCmd(String cmd) {
//        SingleInstruction instruction = new SingleInstruction();
//        instruction.setInstructionId(IdUtil.getUUID_8());
//        instruction.setInstruction(cmd);
//        instruction.setBeforeInstructionName(INSTRUCTION_DEFAULT_HEX);
//        //默认使用com.zhdl.instruction.strategy包下后置策略
//        instruction.setAfterInstructionName(PcbAfterService.PCB_AFTER_SERVICE);
//        //客户端通信地址, 串口为数字, 网口为ip+端口       数据来源 : port_comm 或 port_socket 表
//        instruction.setPortKey("7");
//        //设置协议  数据来源 : protocols 表
//        instruction.setProtocols(PcbAnalysis.PCB_ANALYSIS);
//        behaviorPerform.perform(instruction);
//    }

    /**
     * 发送指令 - 灵活
     *
     * @param cmd 指令
     */
    @Override
    public void sendCmd(String cmd) {
        SingleInstruction instruction = new SingleInstruction();
        instruction.setInstructionId(IdUtil.getUUID_8());
        instruction.setInstruction(cmd);
        instruction.setBeforeInstructionName(INSTRUCTION_DEFAULT_HEX);
        //默认使用com.zhdl.instruction.strategy包下后置策略
        instruction.setAfterInstructionName(PcbAfterService.PCB_AFTER_SERVICE);
        //客户端通信地址, 串口为数字, 网口为ip+端口       数据来源 : port_comm 或 port_socket 表
        instruction.setPortKey("192.168.1.108:502");
//        instruction.setPortKey("127.0.0.1:502");
        //instruction.setPortKey(portConf.getTcpPortIo());
        //设置协议  数据来源 : protocols 表
//        instruction.setProtocols(ModbusAnalysis.MODBUS_TCP_ANALYSIS);
        instruction.setProtocols(MemoBusAnalysisImpl.MODBUS_TCP_ANALYSIS);
        log.info("IO指令发送》》》》》》》》》》》》》》》》》》" + instruction.getInstruction());
        behaviorPerform.perform(instruction);
    }

    /**
     * 读取pcb所有信息
     * 功能码02 读取离散量输入
     */
    @Override
    public void pcbReadInfo(int readBitNumber) {
        //需要判断以下自己需要读取的字节数
        String cmd = PublicTools.getString("cmd", "pcbReadDiscreteSignal");
        sendCmd(cmd);
        log.info("读取到pcb所有信息");
    }

    /**
     * IO-读取离散量输入 功能码02
     * 读取所有信息
     */
    @Override
    public void ioReadDiscreteSignal() {
        //需要判断以下自己需要读取的字节数
        String cmd = PublicTools.getString("cmd", "pcbReadDiscreteSignal");
        sendCmd(cmd);
        log.info("IO-开始读取功能码为02的离散量输入信号");
    }

    /**
     * IO-读取线圈 功能码01
     * 读取所有信息
     */
    @Override
    public void ioReadCoilSignal() {
        //需要判断以下自己需要读取的字节数
        String cmd = PublicTools.getString("cmd", "pcbReadCoilSignal");
        sendCmd(cmd);
        log.info("IO-开始读取功能码为01的线圈输入信号");
    }

    /**
     * IO-写入线圈 功能码05
     * 写入输出量
     */
    @Override
    public void ioWriteCoilSignal(int address, String open) {
        WriteSingleKeepRegisterReq writeManyKeepRegisterReq = new WriteSingleKeepRegisterReq();
        //101
        writeManyKeepRegisterReq.setId("101");
        writeManyKeepRegisterReq.setStartAddr(IntToHexUtil.shortToHex(address));
        //writeManyKeepRegisterReq.setWriteValue(open ? "FF00" : "0000");
        writeManyKeepRegisterReq.setWriteValue(open);
        try {
            byte[] bytes = ModbusTcpRespPkg.write05(writeManyKeepRegisterReq);
            sendCmd(ByteHelper.bytesArrayToHexString(bytes));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * IO-写入多个线圈 功能码0F
     * 写入输出量
     */
    @Override
    public void ioWriteDoubleCoilSignal(int address, boolean open) {
        WriteSingleKeepRegisterReq writeManyKeepRegisterReq = new WriteSingleKeepRegisterReq();
        //101
        writeManyKeepRegisterReq.setId("101");
        writeManyKeepRegisterReq.setStartAddr(IntToHexUtil.shortToHex(address));
        writeManyKeepRegisterReq.setWriteValue(open ? "01" : "02");
        //writeManyKeepRegisterReq.setWriteValue(open);
        try {
            byte[] bytes = ModbusTcpRespPkg.WriteDoubleCoil(writeManyKeepRegisterReq);
            sendCmd(ByteHelper.bytesArrayToHexString(bytes));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 写入pcb信号
     */
    @Override
    public void pcbWriteInfo(int address, String open) {
        log.info("写入pcb信号" + address + open);
        WriteSingleKeepRegisterReq writeManyKeepRegisterReq = new WriteSingleKeepRegisterReq();
        writeManyKeepRegisterReq.setId("01");
        writeManyKeepRegisterReq.setStartAddr(IntToHexUtil.shortToHex(address));
        //writeManyKeepRegisterReq.setWriteValue(open ? "FF00" : "0000");
        writeManyKeepRegisterReq.setWriteValue(open);
        try {
            byte[] bytes = ModbusTcpRespPkg.write05(writeManyKeepRegisterReq);
            sendCmd(ByteHelper.bytesArrayToHexString(bytes));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}
